declare module "tm" {
  namespace Types {
    namespace Xhr {
      interface Const {
        readonly DONE: 4;
        readonly HEADERS_RECEIVED: 2;
        readonly LOADING: 3;
        readonly OPENED: 1;
        readonly RESPONSE_TYPE_ARRAYBUFFER: "arraybuffer";
        readonly RESPONSE_TYPE_BLOB: "blob";
        readonly RESPONSE_TYPE_DOCUMENT: "document";
        readonly RESPONSE_TYPE_JSON: "json";
        readonly RESPONSE_TYPE_STREAM: "stream";
        readonly RESPONSE_TYPE_TEXT: "text";
        readonly UNSENT: 0;
      }
      interface Progress extends CM_Types.Xhr.Progress, Const {
        readonly context?: AnyRecord;
        readonly done?: typeof ProgressEvent.prototype.loaded;
        readonly position?: typeof ProgressEvent.prototype.loaded;
        readonly totalSize?: typeof ProgressEvent.prototype.total;
      }
      interface Response extends CM_Types.Xhr.Response, Const {
        readonly context?: AnyRecord;
        readonly responseType?: Details["responseType"];
      }
      interface ErrorResponse extends CM_Types.Xhr.Response, Const {
        readonly context?: AnyRecord;
        readonly error?: string;
      }
      interface Details extends CM_Types.Xhr.Details {
        anonymous?: boolean;
        context?: AnyRecord;
        cookie?: string;
        cookiePartition?: Parameters<
          typeof browser.cookies.set
        >[0]["partitionKey"];
        data?:
          | string
          | Blob
          | File
          | Record<string | number, unknown>
          | Array<unknown>
          | FormData
          | URLSearchParams;
        fetch?: boolean;
        nocache?: boolean;
        redirect?: RequestRedirect;
        responseType?: "arraybuffer" | "blob" | "json" | "stream" | "text";
        revalidate?: boolean;
        upload?: {
          onprogress?: (e: Progress) => void;
        };
        url: string | URL;
        onabort?: (e: ErrorResponse | Const) => void;
        onerror?: (e: ErrorResponse) => void;
        onload?: (e: Response) => void;
        onloadend?: (e: Response) => void;
        onloadstart?: (e: Response) => void;
        onprogress?: (e: Progress) => void;
        onreadystatechange?: (this: Response, e: Response) => void;
        ontimeout?: (e: Const) => void;
      }
      type PromiseReturn = Promise<Response> & CM_Types.Xhr.Return;
    }
    namespace Download {
      interface Error {
        error: string;
        /*  | `not_${
              | "enabled"
              | "whitelisted"
              | "permitted"
              | "supported"
              | "succeeded"}`
          | "xhr_failed"
          | "aborted"
          | "timeout"
          | typeof XMLHttpRequest.prototype.statusText; */
        details?: string;
      }
      interface Details {
        conflictAction?: browser.downloads.FilenameConflictAction;
        headers?: Parameters<typeof browser.downloads.download>[0]["headers"];
        name?: Parameters<typeof browser.downloads.download>[0]["filename"];
        saveAs?: Parameters<typeof browser.downloads.download>[0]["saveAs"];
        url: Parameters<typeof browser.downloads.download>[0]["url"];
        onload?: (
          this: Record<string, never>,
          e: Record<string, never>,
        ) => void;
        onprogress?: (this: Xhr.Response, e: Xhr.Response) => void;
        onerror?: (this: Error | Xhr.Response, e: Error | Xhr.Response) => void;
        ontimeout?: (e?: Error) => void;
      }
    }
    namespace Notification {
      interface Option extends Partial<CM_Types.Notification.Option> {
        highlight?: boolean;
        silent?: boolean;
        tag?: string;
        timeout?: number;
        url?: string;
        onclick?: (ev: Event) => void;
        ondone?: (clicked: boolean) => void;
      }
    }
    namespace Vcl {
      type cbFunction = (
        this: cbThis,
        name: string,
        oldValue: unknown,
        newValue: unknown,
        remote: boolean,
      ) => void;
      interface cbThis {
        readonly id: number;
        readonly key: string;
        readonly cb: cbFunction;
      }
    }
    namespace OpenTab {
      interface Option {
        active?: boolean;
        incognito?: boolean;
        insert?: boolean;
        setParent?: boolean;
      }
      interface Result {
        close(): void;
        readonly closed: boolean;
        focus(): void;
        name: string | undefined;
        onclose: () => void | null;
      }
    }
    interface ClipboardDataType {
      type?: string;
      mimetype?: string;
    }
    namespace Cookie {
      type Method = "list" | "delete" | "set";
      type SetDetails = Partial<
        Omit<Parameters<typeof browser.cookies.set>[0], "name" | "storeId">
      > & {
        name: string;
        value: string;
      };
      type DeleteDetails = Partial<
        Omit<Parameters<typeof browser.cookies.remove>[0], "storeId">
      >;
      type ListDetails = Omit<
        Parameters<typeof browser.cookies.getAll>[0],
        "session" | "storeId" | "secure" | "firstPartyDomain"
      >;
      type ListCallback = (
        cookies: Omit<browser.cookies.Cookie, "expirationDate" | "storeId">[],
        error: string | undefined,
      ) => void;
      type ChangeCallback = (error?: string) => void;
    }
    namespace WebRequest {
      interface Redirect {
        url: string;
        from?: string;
        to?: string;
      }
      interface Action {
        cancel?: boolean;
        redirect?: string | Redirect;
      }
      interface Selector {
        exclude?: string | string[];
        include?: string | string[];
        match?: string | string[];
      }
      interface Rule {
        action: "cancel" | Action;
        selector: string | Selector;
      }
      interface Details {
        description?: string;
        redirect_url?: string;
        rule: Rule;
        url: string;
      }
    }
    interface Resource {
      readonly content?: string;
      readonly error?: string;
      readonly meta?: string;
      readonly name: string;
      readonly url: string;
    }
    namespace Menu {
      interface Options {
        id?: number | string;
        accessKey?: string;
        autoClose?: boolean;
        title?: string;
      }
    }
  }
}
